<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
        <title>我的百度地图</title>
        <style type="text/css">
            html {
                height: 100%
            }

            body {
                height: 100%;
                margin: 0px;
                padding: 0px
            }

            .helper {
                width: 180px;
                height: 120px;
                font-size: 14px;
                line-height: 26px;
                background-color: #FFFBE5;
                color: black;
                text-align: center;
                border-radius: 4px;
                position: fixed;
                left: calc(50% - 90px);
                top: calc(50% - 60px);
                display: flex;
                flex-direction: column;
                justify-content: center;
                z-index: 9999;
                box-shadow: 0 0 20px black;
            }

            #container {
                height: 100%
            }

            .div1 {
                position: fixed;
                left: calc(50% - 250px);
                top: calc(50% - 200px);
                width: 500px;
                height: 400px;
                padding: 10px;
                border: solid 1px gray;
                background-color: #ccc;
                display: none;
                flex-direction: column;
                align-items: stretch;
                z-index: 9999;
            }

            .div1 textarea {
                margin-bottom: 15px;
            }

            .txt1 {
                flex: 2;
            }

            .txt2 {
                flex: 1;
            }

            .div-buttons {
                height: 32px;
                display: flex;
                flex-direction: row;
                align-items: stretch;
                justify-content: space-between;
            }

            .div-buttons button {
                width: 120px;
            }

            .divCurrent {
                width: 170px;
                height: 30px;
                line-height: 30px;
                text-align: center;
                position: fixed;
                left: 0;
                top: 0;
                z-index: 9999;
                background-color: #769ae0;
                color: white;
                opacity: 0.5;
            }

            .div-radios {
                display: flex;
                flex-direction: row;
                align-items: center;
            }

            .div-radios label {
                margin-right: 12px;
            }
        </style>
        <script type="text/javascript"
            src="https://api.map.baidu.com/api?v=1.0&type=webgl&ak=7034dabc6b9fa4da5eafd90a72884024">
        </script>
        <script type="text/javascript"
            src="https://mapopen.cdn.bcebos.com/github/BMapGLLib/DistanceTool/src/DistanceTool.min.js">
        </script>
    </head>
    <body>
        <div class='helper'>
            Esc键 打开/关闭面板<br />
            鼠标左键 画点<br />
            鼠标右键 删除点<br />
        </div>
        <div class='div1'>
            <textarea rows="5" cols="40" class="txt1"></textarea>
            <textarea rows="5" cols="40" class="txt2"></textarea>
            <div class='div-buttons'>
                <div class='div-radios'>
                    <input type="radio" name='radio1' id='radBD09' value="BD09" /><label for='radBD09'
                        title="经度在前纬度在后。不支持度分秒形式">BD09</label>
                    <input type="radio" name='radio1' id='radWGS84' value="WGS84" /><label for="radWGS84"
                        title=" 纬度在前经度在后。支持度分秒形式">WGS84</label>
                </div>
                <button onclick="btnMapType_onclick();">卫星地图</button>
                <button onclick="btnDraw_onclick();">画</button>
            </div>
        </div>
        <div class="divCurrent">112.53, 23.27</div>
        <div id="container"></div>
        <script type="text/javascript">
            document.querySelector('.txt1').value = `请输入坐标点。格式示例：
22+42'53" 114+32'35 r=800;干货店
22+42.7501 114+31.6203
22°43.3692 114°31.5901 超市
22.70765 114.54693 大厦`;

            function btnMapType_onclick() {
                if (map.getMapType() == BMAP_NORMAL_MAP) {
                    map.setMapType(BMAP_EARTH_MAP);
                } else {
                    map.setMapType(BMAP_NORMAL_MAP);
                }
                document.querySelector('.div1').style.display = 'none';
            }
            window.setTimeout(function() {
                document.querySelector('.helper').style.display = 'none';
            }, 2500);
            let CoordinateType = null;

            function forCoordinateType() {
                CoordinateType = localStorage.getItem('CoordinateType');
                if (!CoordinateType) {
                    CoordinateType = 'WGS84';
                }
                let arr = document.querySelectorAll('.div-radios input');
                for (let i = 0; i < arr.length; i++) {
                    let radio = arr[i];
                    if (radio.value == CoordinateType) {
                        radio.checked = true;
                    }
                    radio.onclick = function() {
                        let value = this.value;
                        CoordinateType = value;
                        localStorage.setItem('CoordinateType', value);
                    }
                }
            }
            forCoordinateType();

            function parseOne(s) {
                if (!s) {
                    return null;
                }
                match = s.match(/[\+°]/);
                if (!match) {
                    return parseFloat(s);
                }
                let degree = s.substr(0, match.index);
                let minute = 0;
                if (match.index < s.length - 1) {
                    minute = s.substr(match.index + 1);
                    let seconds = 0;
                    match = minute.match(/(\d+)'([\d\.]+)?/);
                    if (match) {
                        minute = match[1];
                        if (match[2]) {
                            seconds = match[2];
                            seconds = parseFloat(seconds);
                        }
                    }
                    minute = parseFloat(minute) + seconds / 60;
                }
                degree = parseFloat(degree) + minute / 60;
                return degree;
            }

            function getPointLabel(p) {
                let label = "";
                if (p.label) {
                    label = p.label;
                    let match = label.match(/r=\d+(;(.+))?/);
                    if (match) {
                        if (match[2]) {
                            label = match[2];
                        } else {
                            label = "";
                        }
                    }
                }
                return label;
            }

            function pointToString(p) {
                let s = myRound(p.lng, 5) + ', ' + myRound(p.lat, 5);
                let label = getPointLabel(p);
                if (label) {
                    s += " " + label;
                }
                return s;
            }

            function toBD09(s, callback) {
                let arr = s.trim().split('\n');
                let pointArr = [];
                for (let i = 0; i < arr.length; i++) {
                    let item = arr[i].trim();
                    let arr2 = item.split(/ +/);
                    if (arr2.length < 2) {
                        continue;
                    }
                    var point = new BMapGL.Point(parseOne(arr2[1]), parseOne(arr2[0]));
                    if (arr2[2]) {
                        point.label = arr2[2].trim();
                    }
                    pointArr.push(point);
                }
                window.pointArr = pointArr;
                if (pointArr.length == 0) {
                    callback();
                    return;
                }
                let convertor;
                if (pointArr.length > 5) {
                    let index = -1;
                    let all = [];

                    function cb(data) {
                        if (data) {
                            if (data.status == 0) {
                                for (let i = 0; i < data.points.length; i++) {
                                    all.push(data.points[i]);
                                }
                                if (index >= pointArr.length) {
                                    callback({
                                        status: 0,
                                        points: all
                                    });
                                    return;
                                }
                            } else {
                                console.log('连续转换失败');
                                return;
                            }
                        }
                        if (index < pointArr.length) {
                            let arr = [];
                            for (let i = 1; i <= 5; i++) {
                                index++;
                                if (index < pointArr.length) {
                                    arr.push(pointArr[index]);
                                }
                            }
                            convertor = new BMapGL.Convertor();
                            convertor.translate(arr, 1, 5, cb);
                        }
                    }
                    cb();
                } else {
                    convertor = new BMapGL.Convertor();
                    convertor.translate(pointArr, 1, 5, callback);
                }
            }

            function fromBD09(s, callback) {
                let arr = s.trim().split('\n');
                let pointArr = [];
                for (let i = 0; i < arr.length; i++) {
                    let item = arr[i].trim();
                    let arr2 = item.split(/ +/);
                    if (arr2.length != 2) {
                        continue;
                    }
                    var point = new BMapGL.Point(parseOne(arr2[0]), parseOne(arr2[1]));
                    if (arr2[2]) {
                        point.label = arr2[2].trim();
                    }
                    pointArr.push(point);
                }
                window.pointArr = pointArr;
                if (pointArr.length == 0) {
                    callback();
                    return;
                }
                callback({
                    status: 0,
                    points: pointArr
                });
            }

            function myRound(f, len) {
                let k = Math.pow(10, len);
                f = Math.round(f * k);
                f = f / k;
                return f;
            }

            function addMarker(point, s) {
                var marker = new BMapGL.Marker(point);
                let label = newLabel(s || getPointLabel(point) || pointToString(point));
                marker.setLabel(label);
                map.addOverlay(marker);
                marker.addEventListener('rightclick', function(e) {
                    if (this.shape) {
                        if (this.shape.length) {
                            for (let i = 0; i < this.shape.length; i++) {
                                map.removeOverlay(this.shape[i]);
                            }
                        } else {
                            map.removeOverlay(this.shape);
                        }
                    }
                    map.removeOverlay(this);
                });
                return marker;
            }
            // 画
            function btnDraw_onclick() {
                let s = document.querySelector('.txt1').value.trim();

                function callback(data) {
                    if (data.status == 0) {
                        let point;
                        let arr = []
                        let points = data.points;
                        for (let i = 0; i < points.length; i++) {
                            point = points[i];
                            if (window.pointArr && points.length == window.pointArr.length) {
                                point.label = window.pointArr[i].label;
                            }
                            arr.push(pointToString(point));
                        }
                        document.querySelector('.txt2').value = arr.join('\r\n')
                        if (points.length == 1) {
                            point = points[0];
                            let match = null;
                            if (point.label) {
                                match = point.label.match(/^r=([\d\.]+)/);
                            }
                            if (match) {
                                r = parseFloat(match[1]);
                            } else {
                                r = 1000;
                            }
                            let m = addMarker(point);
                            var circle = new BMapGL.Circle(point, r, {
                                strokeColor: "blue",
                                strokeWeight: 2,
                                strokeOpacity: 0.5
                            });
                            m.shape = circle;
                            map.addOverlay(circle);
                            map.centerAndZoom(point);
                        } else if (points.length > 1 && points.length < 7) {
                            var polyline = new BMapGL.Polyline(points, {
                                strokeColor: "blue",
                                strokeWeight: 2,
                                strokeOpacity: 0.5
                            });
                            map.addOverlay(polyline);
                            map.centerAndZoom(points[0]);
                            for (let i = 0; i < points.length; i++) {
                                let m = addMarker(points[i]);
                                if (i > 0) {
                                    let d = Math.round(GetDistance(points[i - 1], points[i]) / 1000 * 10) / 10;
                                    m.setTitle('离上一点 ' + d + 'Km');
                                } else {
                                    m.setTitle('起点');
                                    m.shape = polyline;
                                }
                            }
                        } else if (points.length >= 7) {
                            map.centerAndZoom(points[0]);
                            for (let i = 0; i < points.length; i++) {
                                let m = addMarker(points[i]);
                            }
                        }
                        document.querySelector('.div1').style.display = 'none';
                    } else {
                        console.log('转换失败', data);
                    }
                }
                if (CoordinateType == 'WGS84') {
                    toBD09(s, callback);
                } else if (CoordinateType == 'BD09') {
                    fromBD09(s, callback);
                }
            }
            //
            var map = new BMapGL.Map("container");
            map.enableScrollWheelZoom();
            var point = new BMapGL.Point(114.55, 22.71);
            map.centerAndZoom(point, 15);
            var scaleCtrl = new BMapGL.ScaleControl(); // 添加比例尺控件
            map.addControl(scaleCtrl);
            var zoomCtrl = new BMapGL.ZoomControl(); // 添加缩放控件
            map.addControl(zoomCtrl);
            var navCtrl = new BMapGL.NavigationControl3D({
                anchor: BMAP_ANCHOR_BOTTOM_RIGHT
            });
            map.addControl(navCtrl);
            //
            map.addEventListener('click', function(e) {
                let s = pointToString(e.latlng);
                document.querySelector('.divCurrent').innerHTML = s;
                //
                let txt2 = document.querySelector('.txt2');
                let value = txt2.value;
                if (value != '' && value.charAt(value.length - 1) != '\n') {
                    value += "\n";
                }
                txt2.value = value + s + "\n";
                //
                let marker = addMarker(e.latlng);
            });
            map.addEventListener('mousemove', function(e) {
                let s = pointToString(e.latlng);
                document.querySelector('.divCurrent').innerHTML = s;
            });

            function newLabel(s, style) {
                let offset = new BMapGL.Size(-34, -38);
                let label = new BMapGL.Label(s, {
                    offset: offset
                });
                var style0 = {
                    border: "1px solid gray",
                    color: "#000",
                    backgroundColor: "#fff",
                    fontSize: "10px",
                    width: "62px",
                    textAlign: 'center',
                    opacity: "0.7",
                    borderRadius: "2px",
                    padding: "1px",
                    whiteSpace: "normal",
                    wordWrap: "break-word",
                };
                style = Object.assign(style0, style);
                label.setStyle(style);
                return label;
            }
            //
            window.onkeyup = function(e) {
                if (event.keyCode == 27) { // Esc
                    let div1 = document.querySelector('.div1');
                    if (div1.style.display == 'flex') {
                        div1.style.display = 'none';
                    } else {
                        div1.style.display = 'flex';
                    }
                }
            }

            function Rad(d) {
                return d * Math.PI / 180.0; //经纬度转换成三角函数中度分表形式。
            }
            //计算距离，参数分别为第一点的纬度，经度；第二点的纬度，经度
            function GetDistance(p1, p2) {
                let lat1 = p1.lat,
                    lng1 = p1.lng,
                    lat2 = p2.lat,
                    lng2 = p2.lng;
                var radLat1 = Rad(lat1);
                var radLat2 = Rad(lat2);
                var a = radLat1 - radLat2;
                var b = Rad(lng1) - Rad(lng2);
                var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(
                        radLat2) *
                    Math.pow(Math.sin(b / 2), 2)));
                s = s * 6378.137; // 地球半径，千米;
                s = Math.round(s * 10000) / 10000; //输出为公里
                s = Math.round(s * 1000) / 1; //单位修改为米,取整
                return s;
            }
            var myDis = new BMapGLLib.DistanceTool(map, {
                lineStroke: 2
            });
            console.log('myDis', myDis);
            var txtMenuItem = [{
                text: '测距',
                callback: function() {
                    if (myDis._isOpen) {
                        myDis.close();
                    } else {
                        myDis.open();
                    }
                }
            }];
            let menu = new BMapGL.ContextMenu();
            for (var i = 0; i < txtMenuItem.length; i++) {
                menu.addItem(new BMapGL.MenuItem(
                    txtMenuItem[i].text,
                    txtMenuItem[i].callback, {
                        width: 100,
                        id: 'menu' + i
                    }
                ));
            }
            map.addContextMenu(menu);
            //
            let disMarker;
            myDis.addEventListener('drawend', function(e) {
                if (disMarker) {
                    disMarker.shape = e.overlays;
                }
            });
            myDis.addEventListener("addpoint", function(e) {
                disMarker = addMarker(e.point);
                let value = document.querySelector('.txt2').value;
                if (value && value.charAt(value.length - 1) != '\n') {
                    value += "\n";
                }
                value += pointToString(e.point);
                document.querySelector('.txt2').value = value;
            });
        </script>
    </body>
</html>
